package io.github.uicdb.badskill;

import com.google.common.reflect.TypeToken;
import com.google.gson.JsonElement;
import io.github.uicdb.badskill.codec.JsonFactory;
import lombok.*;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;

import java.util.*;

@EqualsAndHashCode
@ToString
@Builder
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class SkillPage {
    public ResourceLocation id;
    @Nullable
    public ResourceLocation icon;
    @Nullable
    public ResourceLocation background;

    public Map<ResourceLocation,Location> locations;

    public List<ImageLocation> imageLocations;
    public JsonElement toJson(){
        return JsonFactory.create()
                .toJsonTree(this,SkillPage.class);
    }
    private SkillPage(){

    }
    public static SkillPage fromJson(JsonElement element){
        var obj=element.getAsJsonObject();
        ResourceLocation page=JsonFactory.create().fromJson(obj.get("id"),ResourceLocation.class);
        SkillPage p=new SkillPage();
        p.id =page;
        if(obj.has("locations"))
        p.locations=JsonFactory.create().fromJson(obj.get("locations"),new TypeToken<Map<ResourceLocation,Location>>(){}.getType());
        if(obj.has("imageLocations"))
            p.imageLocations=JsonFactory.create().fromJson(obj.get("imageLocations"),new TypeToken<List<ImageLocation>>(){}.getType());
        if(obj.has("icon")){
            p.icon=new ResourceLocation(obj.get("icon").getAsString());
        }
        if(obj.has("background")){
            p.background=new ResourceLocation(obj.get("background").getAsString());
        }
        return p;
    }
    public void toNetwork(FriendlyByteBuf buf){
        buf.writeResourceLocation(id);
        buf.writeBoolean(icon!=null);
        if(icon!=null){
            buf.writeResourceLocation(icon);
        }
        buf.writeBoolean(background!=null);
        if(background!=null){
            buf.writeResourceLocation(background);
        }
         buf.writeMap(locations, FriendlyByteBuf::writeResourceLocation, (buf1, location) -> location.toNetwork(buf1));
        buf.writeCollection(imageLocations, (buf12, imageLocation) -> imageLocation.toNetwork(buf12));
    }

    public static SkillPage fromNetwork(FriendlyByteBuf buf){
        SkillPage page=new SkillPage();
        page.id =buf.readResourceLocation();
        if(buf.readBoolean()){
            page.icon=buf.readResourceLocation();
        }
        if(buf.readBoolean()){
            page.background=buf.readResourceLocation();
        }
        page.locations=buf.readMap(FriendlyByteBuf::readResourceLocation, Location::fromNetwork);
        page.imageLocations=buf.readList(ImageLocation::fromNetwork);
        return page;
    }
@EqualsAndHashCode@ToString
    public static final class Location {
    public  int x;
    public  int y;
    public  int width=16;
    public  int height=16;
    public  @Nullable ResourceLocation icon;
    public @Nullable ResourceLocation learnedIcon;
    public  List<ResourceLocation> parents=new ArrayList<>();
        public Location(int x, int y,int width,int height, @Nullable ResourceLocation icon,@Nullable ResourceLocation learnedIcon, List<ResourceLocation> parents) {
            this.x = x;
            this.y = y;
            this.width=width;
            this.height=height;
            this.icon = icon;
            this.parents = parents;
            this.learnedIcon=learnedIcon;
        }


    static Location create(int x, int y, int width, int height, @Nullable ResourceLocation icon, @Nullable ResourceLocation learnedIcon, ResourceLocation... parents) {
            return new Location(x, y, width,height,icon,learnedIcon, List.of(parents));
        }

        public void toNetwork(FriendlyByteBuf buf) {
            buf.writeInt(x);
            buf.writeInt(y);
            buf.writeInt(width);
            buf.writeInt(height);
            buf.writeBoolean(icon != null);
            if (icon != null) {
                buf.writeResourceLocation(icon);
            }
            buf.writeBoolean(learnedIcon != null);
            if(learnedIcon!=null)
                buf.writeResourceLocation(learnedIcon);
            buf.writeCollection(parents, FriendlyByteBuf::writeResourceLocation);
        }

        public static Location fromNetwork(FriendlyByteBuf buf) {
            int x = buf.readInt();
            int y = buf.readInt();
            int width=buf.readInt();
            int height=buf.readInt();
            ResourceLocation icon = null;
            if (buf.readBoolean()) {
                icon = buf.readResourceLocation();
            }
            ResourceLocation learned = null;
            if (buf.readBoolean()) {
                learned = buf.readResourceLocation();
            }
            List<ResourceLocation> array = buf.readList(FriendlyByteBuf::readResourceLocation);
            return new Location(x, y,width,height, icon,learned, array);
        }

    }
    public static final class ImageLocation{
        public ResourceLocation location;
        public int x,y,width,height;

        public ImageLocation(ResourceLocation location, int x, int y, int width, int height) {
            this.location = location;
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
        }

        public void toNetwork(FriendlyByteBuf buf){
            buf.writeResourceLocation(location);
            buf.writeInt(x);
            buf.writeInt(y);
            buf.writeInt(width);
            buf.writeInt(height);
        }
        public static ImageLocation fromNetwork(FriendlyByteBuf buf){
            return new ImageLocation(buf.readResourceLocation(),buf.readInt(),buf.readInt(),buf.readInt(),buf.readInt());
        }
    }
}
